<template>
  <div>
    <el-row>
      <el-col :span="4" style="width: 180px">
        <el-tree
          default-expand-all
          :data="navJson"
          :props="defaultProps"
          highlight-current
          :expand-on-click-node="false"
        >
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>{{ node.label }}</span>
            <span style="margin-left: 7px">
              <!-- 增加 -->
              <i
                v-if="node.level !== 3"
                class="el-icon-circle-plus-outline addicon"
                @click="() => appendNode(node, data)"
                title="新增菜单"
              ></i>

              <!-- 修改 -->
              <i
                class="el-icon-edit-outline updateicon"
                @click="() => updateNode(node, data)"
                title="修改菜单"
              ></i>

              <!-- 删除 -->
              <i
                class="el-icon-circle-close removeicon"
                @click="() => removeNode(node, data)"
                title="删除菜单"
              ></i>
            </span>
          </span>
        </el-tree>
      </el-col>
      <el-col :span="15">
        <el-form :model="form" :rules="rules" ref="form" label-width="100px">
          <el-form-item label="父菜单名称" prop="name" v-if="!uppdateNode">
            <el-input v-model="form.name" disabled></el-input>
          </el-form-item>
          <el-form-item label="父菜单路径" prop="path" v-if="!uppdateNode">
            <el-input v-model="form.path" disabled></el-input>
          </el-form-item>
          <el-form-item label="菜单名称" prop="addname">
            <el-input v-model="form.addname"></el-input>
          </el-form-item>
          <el-form-item label="菜单路径" prop="addpath">
            <el-input v-model="form.addpath"></el-input>
          </el-form-item>
          <el-form-item label="菜单图标" prop="addicon">
            <el-input v-model="form.addicon"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button v-if="uppdateNode" type="primary" @click="saveUpdate"
              >保存修改</el-button
            >
            <el-button v-else type="primary" @click="onSubmit"
              >添加菜单</el-button
            >
            <el-button type="danger" @click="removeCookie">重置菜单</el-button>
          </el-form-item>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // tree数据
      navJson: [],
      // tree展示的节点和文本
      defaultProps: {
        children: "children",
        label: "name",
      },
      // 当前点击的节点属性
      nowClickNode: null,
      // 当前点击的节点信息
      nowClickData: null,
      // 添加的菜单表单
      form: {
        path: "",
        name: "",
        addname: "",
        addpath: "",
        addicon: "",
      },
      // 表单验证规则
      rules: {
        name: [
          {
            required: true,
            message: "请选择左侧菜单进行操作",
            trigger: "change",
          },
        ],
        path: [
          {
            required: true,
            message: "请选择左侧菜单进行操作",
            trigger: "change",
          },
        ],
        addname: [
          { required: true, message: "该项不能为空", trigger: "change" },
        ],
        addpath: [
          { required: true, message: "该项不能为空", trigger: "change" },
        ],
        addicon: [
          { required: true, message: "该项不能为空", trigger: "change" },
        ],
      },
      // 标记是否点击的修改按钮
      uppdateNode: false,
    };
  },
  mounted() {
    // 从cookie中读取菜单数据
    if (this.cookie.getCookie("navJson")) {
      this.navJson = JSON.parse(this.cookie.getCookie("navJson"));
    }
  },
  methods: {
    // 添加菜单
    appendNode(node, data) {
      // 标记当前点击的不是修改按钮
      this.uppdateNode = false;
      // 获取当前点击的节点属性
      this.nowClickNode = node;
      this.nowClickData = data;
      // 获取当前点击的节点名称
      this.form = JSON.parse(JSON.stringify(data));
      // 判断点击的是第几级菜单
      let level = node.level;
      // 获取到当前点击的菜名名称
      this.form.name = node.label;
    },
    // 删除
    removeNode(node, data) {
      // 判断点击的是第几级菜单
      let level = node.level;
      // 获取到当前点击的菜名名称
      let label = node.label;
      // 删除一级菜单
      if (level === 1) {
        let rootNodeIndex = this.navJson.findIndex(
          (item) => item.name === label
        );
        // 删除提示框
        this.showRemoveMessage(label, level, rootNodeIndex);
      }
      if (level === 2) {
        // 获取子菜单的父级名称
        let parentLabel = node.parent.label;
        // 获取点击的子菜单的父级在数组中的位置
        let parentLabelIndex = this.navJson.findIndex(
          (item) => item.name === parentLabel
        );
        // 获取子菜单的名称
        let label = node.label;
        // 获取子菜单在父级中的位置
        let labelIndex = this.navJson[parentLabelIndex].children.findIndex(
          (item) => item.name === label
        );
        // 删除提示框
        this.showRemoveMessage(label, level, parentLabelIndex, labelIndex);
      }
      if (level === 3) {
        // 获取根节点名称
        let rootLabel = node.parent.parent.label;
        // 获取根节点下标
        let rootIndex = this.navJson.findIndex(
          (item) => item.name === rootLabel
        );
        // 获取父节点名称
        let parenLabel = node.parent.label;
        // 获取父节点下标
        let parenIndex = this.navJson[rootIndex].children.findIndex(
          (item) => item.name === parenLabel
        );
        // 获取节点名称
        let label = node.label;
        // 获取节点下标
        let index = this.navJson[rootIndex].children[
          parenIndex
        ].children.findIndex((item) => item.name === label);

        // 删除提示框
        this.showRemoveMessage(label, level, rootIndex, parenIndex, index);
      }
    },
    // 删除提示框
    showRemoveMessage(label, level, rootIndex, parenIndex, index) {
      // 弹框提示
      this.$confirm(`您正在删除【${label}】节点, 是否继续?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          if (level === 1) {
            // 删除操作
            this.navJson.splice(rootIndex, 1);
          }
          if (level === 2) {
            // 删除操作
            this.navJson[rootIndex].children.splice(parenIndex, 1);
          }
          if (level === 3) {
            // 删除数据操作
            this.navJson[rootIndex].children[parenIndex].children.splice(
              index,
              1
            );
          }
          // 保存菜单的JSON到Cookie
          this.setNavJsonCookie();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    // 修改菜单
    updateNode(node, data) {
      console.log(data);
      this.uppdateNode = true;
      this.form = {
        path: "",
        name: "",
        addname: "",
        addpath: "",
        addicon: "",
      };
      // 回填节点名称
      this.form.addname = data.name;
      // 回填节点路径
      this.form.addpath = data.path;
      // 回填节点路图标
      this.form.addicon = data.icon;
      this.$forceUpdate();
      // 获取当前点击的节点属性
      this.nowClickNode = node;
      this.nowClickData = data;
    },
    // 保存修改
    saveUpdate() {
      let node = this.nowClickNode;
      let data = this.nowClickData;
      let newName = this.form.addname;
      let newPath = this.form.addpath;
      let newIcon = this.form.addicon;
      // 获取当前节点等级
      let nodeLevel = node.level;
      // 获取当前节点名称
      let nodeLabel = node.label;
      // 修改根节点
      if (nodeLevel === 1) {
        let rootIndex = this.navJson.findIndex(
          (item) => item.name === node.label
        );
        this.navJson[rootIndex].name = newName;
        this.navJson[rootIndex].path = newPath;
        this.navJson[rootIndex].icon = newIcon;
        // 显示提示框
        this.showUpdataMessage(nodeLabel);
      }
      // 修改二级菜单
      if (nodeLevel === 2) {
        // 获取子菜单的父级名称
        let parentLabel = node.parent.label;
        // 获取点击的子菜单的父级在数组中的位置
        let parentIndex = this.navJson.findIndex(
          (item) => item.name === parentLabel
        );
        // 获取子菜单的名称
        let label = node.label;
        // 获取子菜单在父级中的位置
        let labelIndex = this.navJson[parentIndex].children.findIndex(
          (item) => item.name === label
        );

        this.navJson[parentIndex].children[labelIndex].name = newName;
        this.navJson[parentIndex].children[labelIndex].path = newPath;
        this.navJson[parentIndex].children[labelIndex].icon = newIcon;
        // 显示提示框
        this.showUpdataMessage(nodeLabel);
      }
      // 修改三级菜单
      if (nodeLevel === 3) {
        // 获取根节点名称
        let rootLabel = node.parent.parent.label;
        // 获取根节点下标
        let rootIndex = this.navJson.findIndex(
          (item) => item.name === rootLabel
        );

        // 获取父节点名称
        let parenLabel = node.parent.label;
        // 获取父节点下标
        let parenIndex = this.navJson[rootIndex].children.findIndex(
          (item) => item.name === parenLabel
        );

        // 获取节点名称
        let label = node.label;
        // 获取节点下标
        let index = this.navJson[rootIndex].children[
          parenIndex
        ].children.findIndex((item) => item.name === label);

        // 更新菜单名称
        this.navJson[rootIndex].children[parenIndex].children[
          index
        ].name = newName;
        // 更新菜单路径
        this.navJson[rootIndex].children[parenIndex].children[
          index
        ].path = newPath;
        // 更新菜单图标
        this.navJson[rootIndex].children[parenIndex].children[
          index
        ].icon = newIcon;
        // 显示提示框
        this.showUpdataMessage(nodeLabel);
      }
    },
    // 显示修改确认框
    showUpdataMessage(nodeLabel) {
      // 弹框提示
      this.$confirm(`您正在修改【${nodeLabel}】节点的信息，是否保存`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          // 修改确认弹框
          this.$message({
            type: "success",
            message: "修改成功!",
          });
          // 保存菜单的JSON到Cookie
          this.setNavJsonCookie();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消修改",
          });
        });
    },
    // 添加菜单
    onSubmit() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          // 当前点击的菜单级别
          let level = this.nowClickNode.level;
          // 获取跟菜单在数组中的位置
          let nowClickLabelIndex = this.navJson.findIndex(
            (item) => item.name === this.nowClickNode.label
          );
          // 如果等于1表示在该根节点下添加子菜单
          if (level === 1) {
            // 往该根节点添加子菜单
            this.navJson[nowClickLabelIndex].children.push({
              name: this.form.addname,
              path: this.form.addpath,
              icon: this.form.addicon,
            });
          } else {
            // 获取子菜单的父级名称
            let parentLabel = this.nowClickNode.parent.label;
            // 获取点击的子菜单的父级在数组中的位置
            let parentLabelIndex = this.navJson.findIndex(
              (item) => item.name === parentLabel
            );
            // 获取子菜单的名称
            let label = this.nowClickNode.label;
            // 获取子菜单在父级中的位置
            let labelIndex = this.navJson[parentLabelIndex].children.findIndex(
              (item) => item.name === label
            );
            // 当前点击的子节点
            let nowClickNode = this.navJson[parentLabelIndex].children[
              labelIndex
            ];
            // 如果以及菜单没有子菜单添加一个空数组
            if (!nowClickNode.children) {
              nowClickNode.children = [];
            }
            // 往二级菜单中添加数据
            nowClickNode.children.push({
              name: this.form.addname,
              path: this.form.addpath,
              icon: this.form.addicon,
            });
          }
          // 提示成功弹框
          this.$confirm("是否确定添加菜单?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          })
            .then(() => {
              this.$message({
                type: "success",
                message: "添加成功",
              });
              // 保存菜单的JSON到Cookie
              this.setNavJsonCookie();
            })
            .catch(() => {
              this.$message({
                type: "info",
                message: "已取消",
              });
              setTimeout(() => {
                this.$router.go(0);
              }, 500);
            });
        }
      });
    },
    // 保存菜单的JSON到Cookie
    setNavJsonCookie() {
      // 封装数据到cookie
      let navCookieJson = {
        navJson: JSON.stringify(this.navJson),
      };
      // 调用setCookie方法，同时传递需要存储的json数据，保存天数
      this.cookie.setCookie(navCookieJson, 7);
      //  延迟刷新页面
      setTimeout(() => {
        this.$router.go(0);
      }, 700);
    },
    // 删除Cookie
    removeCookie() {
      this.$confirm("确定重置菜单吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$message({
            type: "success",
            message: "成功",
          });
          this.cookie.clearCookie("navJson");
          setTimeout(() => {
            this.$router.go(0);
          }, 1000);
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消",
          });
        });
    },
  },
};
</script>
<style  scoped>
.el-tree {
  cursor: default;
  background: #f2f2f2 !important;
  color: #606266;
  width: 100%;
  height: 95vh;
}
.addicon {
  color: #109eeb;
}
.removeicon {
  color: #f56c6c;
}
.updateicon {
  color: #04be02;
}
</style>
